contents

러스트(Rust)성능, 신뢰성, 생산성이라는 세 가지에 초점을 맞춘 현대적인 시스템 프로그래밍 언어입니다. 가장 유명하고 결정적인 특징은 가비지 컬렉터 없이 메모리 안전성을 달성한다는 점입니다. 이 덕분에 성능이 중요한 작업에서 C++을 대체할 강력한 언어로, 그리고 안전하고 동시성 있는 소프트웨어를 구축하는 데 매력적인 선택지로 자리매김하고 있습니다.


러스트의 핵심 철학 🎯

러스트는 C++과 같은 언어의 높은 성능과 자바나 파이썬 같은 언어의 안전성 사이의 오랜 트레이드오프를 해결하기 위해 설계되었습니다. 러스트는 두 가지 모두를 제공하는 것을 목표로 합니다.


"마법": 소유권, 빌림, 생명주기 ✨

러스트의 가장 큰 혁신은 메모리를 관리하기 위해 컴파일러가 확인하는 규칙들의 집합인 소유권 시스템입니다. 이 시스템 덕분에 러스트는 가비지 컬렉터 없이도 메모리 안전성을 확보할 수 있습니다.

1. 소유권 (Ownership)

이것이 핵심 규칙입니다. 러스트의 모든 값은 그 값의 소유자인 변수를 가집니다.

비유: 값을 애완동물이라고 생각할 수 있습니다. 애완동물은 단 한 명의 주인만 가질 수 있습니다. 주인이 이사 가면 애완동물도 함께 갑니다. 이는 다른 언어에서 흔한 "메모리 누수"(잊혀진 애완동물)를 방지합니다.

fn main() {
    let s1 = String::from("hello"); // s1이 "hello" 문자열을 소유함
    let s2 = s1; // "hello"의 소유권이 s1에서 s2로 이동(MOVED)됨

    // 아래 코드는 s1이 더 이상 아무것도 소유하지 않으므로 컴파일 오류를 발생시킴!
    // println!("{}", s1); 
} // s2가 스코프를 벗어나면서 "hello"가 해제되고 메모리가 반환됨.

2. 빌림 (Borrowing, 참조)

만약 소유권이 항상 이동한다면 매우 불편할 것입니다. 그래서 러스트는 참조(reference) 를 사용하여 값에 대한 접근을 "빌릴" 수 있게 해줍니다.

컴파일러는 이러한 규칙을 강제하여 동시성 프로그래밍에서 흔하고 고약한 버그인 데이터 경쟁(data race) 을 방지합니다.

fn calculate_length(s: &String) -> usize { // s는 String에 대한 참조
    s.len()
} // s는 스코프를 벗어나지만, 데이터를 소유하지 않으므로 아무것도 해제되지 않음.

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1); // s1에 대한 참조를 전달
    println!("'{}'의 길이는 {}입니다.", s1, len); // s1은 여기서 여전히 유효함!
}

3. 생명주기 (Lifetimes)

생명주기는 컴파일러가 참조가 그것이 가리키는 데이터보다 오래 살아남지 않도록 보장하는 방법입니다. 이는 댕글링 포인터(해제된 메모리에 대한 참조)를 방지합니다. 대부분의 경우 컴파일러가 생명주기를 자동으로 추론할 수 있지만, 때로는 컴파일러를 돕기 위해 명시적인 생명주기 어노테이션('a)을 추가해야 합니다.


기타 주요 특징


일반적인 사용 사례 🚀

러스트의 성능과 안전성의 독특한 조합은 다양한 애플리케이션에 적합합니다.


장점과 단점 ⚖️

장점

단점

references